import React from "react";
import Schema from "./asyncValidator";
export interface formInstanceProps {
  setInitialValues: (initialValues: any, mounted: any) => void;
  registerField: (FieldEntity: any) => void;
  setFieldValue: (name: any, value: any) => void;
  setFieldsValue: (newStore: any) => void;
  getFieldsValue: any;
  getFieldValue: (name: any) => any;
  setCallbacks: (callbacks: any) => void;
  submit: () => void;
}
class FormStore {
  store: any;
  callbacks: any;
  forceUpdate: any;
  fieldEntities: any;
  constructor(forceUpdate: any) {
    this.forceUpdate = forceUpdate;
    this.store = {}; //用来存放表单值的对象,输入框输入的值会放到这个里面，也会从这个里面取值
    this.callbacks = {};
    this.fieldEntities = []; //字段的实体数组
  }

  //注册字段的实例
  registerField = (fieldEntity: any) => {
    this.fieldEntities.push(fieldEntity);
  };
  //设置字段的值，取值
  setFieldsValue = (newStore: any) => {
    this.store = { ...this.store, ...newStore }; //把newStore里的属性都赋值给this.store
    // this.fieldEntities.forEach((entity:any) => {

    //     this.forceUpdate(this.store)
    // });
  };
  //获取某个字段的值，改值
  getFieldValue = (name: any) => { 
    return this.store[name]; //获取store中某个属性的名字
  };

  getFieldsValue = () => {
    return this.store; //获取store
  };
  //设置回调函数
  setCallbacks = (callbacks: any) => {
    this.callbacks = callbacks;
  };
  //设置字段的值
  // setFieldValue = (name: any, value: any) => {
  //   this.store[name] = value;
   
    
  //   this.fieldEntities.forEach((entity: any) => {
  //     entity.onStoreChange();
  //   });
  // };
  setInitialValues = (initialValues: any, mounted: any) => {
    if (!mounted) {
      this.store = { ...initialValues };
    }
  };
  submit = () => { 
    this.validateFields()
      .then((values: any) => {
        let { onFinish } = this.callbacks;
        if (onFinish) {
          onFinish(values);
        }
      })
      .catch((errorInfo: any) => {
        let { onFinishFailed } = this.callbacks;
        if (onFinishFailed) {
          onFinishFailed(errorInfo);
        }
      });
  };


  //校验表单的值

  validateFields = () => {
    let values = this.getFieldsValue();  //store
    let descriptor = this.fieldEntities.reduce(
      (descriptor: any, entity: any) => {
        let rules = entity.props.rules; //[{required:true,min:3}]
        if (rules && rules.length) {
          let config = rules.reduce((config: any, rule: any) => {
            config = { ...config, ...rule };
           
            return config; //{required:true,min:3}
          }, {});
       
          
          
          descriptor[entity.props.name] = config;
        }
       
        return descriptor;
      },
      {}
    );
    return new Schema(descriptor).validate(values);
  };
  //希望隐藏一些私有方法
  getForm = () => {
    return {
      registerField: this.registerField,
      setInitialValues: this.setInitialValues,
      // setFieldValue: this.setFieldValue,
      setFieldsValue: this.setFieldsValue,
      getFieldValue: this.getFieldValue,
      getFieldsValue: this.getFieldsValue,
      setCallbacks: this.setCallbacks,
      submit: this.submit,
    };
  };
}

//自定义hooks就是一个用use开头的函数，里面用到了其他hooks
export default function useForm() {
  let formRef = React.useRef<any>(); //{current:null} formRef可以在多次组件渲染保持current不变，返回一个对象，用来返回一个实例，而不是每一次都创建一个实例
  //强行刷新组件的方法
  let [value, forceUpdate] = React.useState({});
  if (!formRef.current) {  //第一次current是null
    // const forceReRender = () => {
    //   forceUpdate({}); //调用此方法可以让组件刷新
    // };
    let formStore = new FormStore(forceUpdate);
    let formInstance: any = formStore.getForm();
    formRef.current = formInstance;
  }
  //一般来说自定义hooks都会返回数组，方便扩展
  return formRef.current;
}
